home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-06-01 | 41.8 KB | 1,703 lines |
- |##########|
- |#MAGIC #|BOPDNEAN
- |#PROJECT #|"OFunctions"
- |#PATHS #|"Project2.0"
- |#FLAGS #|xx-x-x--x---xxx-----------------
- |#USERSW #|--------------------------------
- |#USERMASK#|--------------------------------
- |#SWITCHES#|x----x----------
- |##########|
- $$TypeChk:=FALSE
- IMPLEMENTATION MODULE OFunctions;
-
- FROM Resources IMPORT ContextPtr,New,Dispose;
- FROM Exceptions IMPORT DivisionByZero,RangeViolation;
- FROM Conversions IMPORT StringToReal,RealToString;
- FROM Strings IMPORT Append;
- FROM Str IMPORT CapsEqual;
-
- IMPORT OLists,ODictionaries;
-
- TYPE
- Variable = POINTER TO VariableObj;
- Expression = POINTER TO ExpressionObj;
-
- DEFINITION MODULE ExLists = OLists.BiLists(Expression);
-
-
- TYPE
- ExpressionObj = OBJECT OF ExLists.Node;
- CONSTRUCTOR Create(func : Function):Expression;
- DESTRUCTOR Delete;
- DEFERRED METHOD FClone(func : Function):Expression;
-
- DEFERRED METHOD Eval():LONGREAL;
- DEFERRED METHOD Compile;
- DEFERRED METHOD Diff(func : Function;
- after : Variable):Expression;
-
- DEFERRED METHOD AppendOn(VAR str : STRING);
- DEFERRED METHOD StringLen():INTEGER;
- $$OwnHeap:=TRUE
- METHOD toString():STRING;
- END;
-
- Constant = POINTER TO OBJECT OF Expression;
- value : LONGREAL;
- CONSTRUCTOR Create(func : Function;
- value : LONGREAL):Expression;
- METHOD FClone(func : Function):Expression;
-
- METHOD Eval():LONGREAL;
- METHOD Diff(func : Function;
- after : Variable):Expression;
-
- METHOD AppendOn(VAR str : STRING);
- METHOD StringLen():INTEGER;
- END;
-
- ExpressionList = POINTER TO OBJECT OF Expression,ExLists.List;
- DESTRUCTOR Delete;
- METHOD FClone(func : Function):Expression;
- END;
-
-
- Summation = POINTER TO OBJECT OF ExpressionList;
- METHOD Diff(func : Function;
- after : Variable):Expression;
- METHOD Eval():LONGREAL;
- METHOD AppendOn(VAR str : STRING);
- METHOD StringLen():INTEGER;
- END;
-
- Product = POINTER TO OBJECT OF ExpressionList;
- METHOD Diff(func : Function;
- after : Variable):Expression;
- METHOD Eval():LONGREAL;
- METHOD AppendOn(VAR str : STRING);
- METHOD StringLen():INTEGER;
- END;
-
- SimpleFunction = POINTER TO OBJECT OF Expression;
- of : Expression;
- CONSTRUCTOR Create(func : Function;
- of : Expression):Expression;
- DESTRUCTOR Delete;
- METHOD FClone(func : Function):Expression;
- END;
-
- Negation = POINTER TO OBJECT OF SimpleFunction;
- METHOD Diff(func : Function;
- after : Variable):Expression;
- METHOD Eval():LONGREAL;
- METHOD AppendOn(VAR str : STRING);
- METHOD StringLen():INTEGER;
- END;
-
- Reciproke = POINTER TO OBJECT OF SimpleFunction;
- METHOD Diff(func : Function;
- after : Variable):Expression;
- METHOD Eval():LONGREAL;
- METHOD AppendOn(VAR str : STRING);
- METHOD StringLen():INTEGER;
- END;
-
- VariableObj = OBJECT OF Expression;
- value : LONGREAL;
- name : STRING(20);
- METHOD Eval():LONGREAL;
- METHOD Diff(func : Function;
- after : Variable):Expression;
- CONSTRUCTOR Create( func : Function;
- REF name : STRING);
- METHOD FClone(func : Function):Expression;
-
- METHOD AppendOn(VAR str : STRING);
- METHOD StringLen():INTEGER;
- END;
-
- Potenz = POINTER TO OBJECT OF Expression;
- base,
- exponent : Expression;
- CONSTRUCTOR Create(func : Function;
- base,ex : Expression):Expression;
- DESTRUCTOR Delete;
- METHOD FClone(func : Function):Expression;
- METHOD Diff(func : Function;
- after : Variable):Expression;
-
- METHOD Eval():LONGREAL;
- METHOD AppendOn(VAR str : STRING);
- METHOD StringLen():INTEGER;
- END;
-
- Indirection = POINTER TO OBJECT OF SimpleFunction;
- METHOD Diff(func : Function;
- after : Variable):Expression;
- DESTRUCTOR Delete;
-
- METHOD Eval():LONGREAL;
- METHOD AppendOn(VAR str : STRING);
- METHOD StringLen():INTEGER;
- END;
-
- DEFINITION MODULE VarDicts = ODictionaries.TextDicts(Variable);
-
- TYPE
- VarDict = VarDicts.Dictionary;
-
- PROCEDURE BuildSum(func : Function;
- left,right : Expression):Expression;
-
- PROCEDURE AddToSum(prod : Summation;
- const : Constant):Expression;
- VAR ex : Expression;
- BEGIN
- ex:=prod.first;
- WHILE ex#NIL
- AND_WHILE NOT (ex IS Constant) DO
- ex:=ex.next
- ELSE
- Constant(ex).value:=Constant(ex).value+const.value;
- const.Delete;
- IF Constant(ex).value=0.0 THEN
- prod.RemoveNode(ex);
- IF prod.first=prod.last THEN
- ex:=prod.first;
- prod.RemoveNode(ex);
- prod.Delete;
- RETURN ex;
- ELSE
- RETURN prod
- END;
- ELSE
- RETURN prod;
- END;
- END
- ELSE
- prod.InsertLast(const);
- RETURN prod
- END;
- END AddToSum;
-
- PROCEDURE JoinSumms(left,right : Summation):Expression;
- VAR const : Constant;
- ex : Expression;
- BEGIN
- ex:=left.first;
- WHILE (ex#NIL) AND NOT (ex IS Constant) DO
- ex:=ex.next;
- END;
- const:=ex;
-
- WHILE right.first#NIL DO
- ex:=right.first;
- right.RemoveNode(ex);
- IF (const#NIL) AND (ex IS Constant) THEN
- const.value:=const.value+Constant(ex).value;
- ex.Delete;
- IF const.value=0.0 THEN
- left.RemoveNode(const);
- const.Delete;
- const:=NIL
- END;
- ELSE
- left.InsertLast(ex)
- END;
- END;
- right.Delete;
- RETURN left;
- END JoinSumms;
-
- VAR sum : Summation;
- BEGIN
- IF left IS Constant
- AND_IF Constant(left).value=0.0 THEN
- left.Delete;
- RETURN right
- OR_IF right IS Constant THEN
- Constant(left).value:=Constant(left).value+Constant(right).value;
- right.Delete;
- RETURN left
- END
- OR_IF right IS Constant
- AND_IF Constant(right).value=0.0 THEN
- right.Delete;
- RETURN left
- END
- OR_IF left IS Summation THEN
- IF right IS Summation THEN
- RETURN JoinSumms(left,right);
- OR_IF right IS Constant THEN
- RETURN AddToSum(left,right);
- ELSE
- Summation(left).InsertLast(right);
- RETURN left
- END
- OR_IF right IS Summation THEN
- IF left IS Constant THEN
- RETURN AddToSum(right,left)
- ELSE
- Summation(right).InsertLast(left);
- RETURN right
- END
- ELSE
- sum:=Summation.Create(func);
- sum.InsertLast(left);
- sum.InsertLast(right);
- RETURN sum
- END;
- END BuildSum;
-
- PROCEDURE BuildProduct(func : Function;
- left,right : Expression):Expression;
-
- PROCEDURE AddToProduct(prod : Product;
- const : Constant):Expression;
- VAR ex : Expression;
- BEGIN
- ex:=prod.first;
- WHILE ex#NIL
- AND_WHILE NOT (ex IS Constant) DO
- ex:=ex.next
- ELSE
- Constant(ex).value:=Constant(ex).value*const.value;
- const.Delete;
- IF Constant(ex).value=1.0 THEN
- prod.RemoveNode(ex);
- IF prod.first=prod.last THEN
- ex:=prod.first;
- prod.RemoveNode(ex);
- prod.Delete;
- RETURN ex;
- ELSE
- RETURN prod
- END;
- ELSE
- RETURN prod;
- END;
- END
- ELSE
- prod.InsertLast(const);
- RETURN prod
- END;
- END AddToProduct;
-
- PROCEDURE JoinProducts(left,right : Product):Expression;
- VAR const : Constant;
- ex : Expression;
- BEGIN
- ex:=left.first;
- WHILE (ex#NIL) AND NOT (ex IS Constant) DO
- ex:=ex.next;
- END;
- const:=ex;
-
- WHILE right.first#NIL DO
- ex:=right.first;
- right.RemoveNode(ex);
- IF (const#NIL) AND (ex IS Constant) THEN
- const.value:=const.value*Constant(ex).value;
- ex.Delete;
- IF const.value=1.0 THEN
- left.RemoveNode(const);
- const.Delete;
- const:=NIL
- END;
- ELSE
- left.InsertLast(ex)
- END;
- END;
- right.Delete;
- RETURN left;
- END JoinProducts;
-
- VAR prod : Product;
-
- BEGIN
- IF left IS Constant
- AND_IF Constant(left).value=0.0 THEN
- right.Delete;
- RETURN left
- OR_IF Constant(left).value=1.0 THEN
- left.Delete;
- RETURN right
- OR_IF right IS Constant THEN
- Constant(left).value:=Constant(left).value*Constant(right).value;
- right.Delete;
- RETURN left;
- END
- OR_IF right IS Constant
- AND_IF Constant(right).value=0.0 THEN
- left.Delete;
- RETURN right
- OR_IF Constant(right).value=1.0 THEN
- right.Delete;
- RETURN left
- END
- OR_IF left IS Product THEN
- IF right IS Product THEN
- RETURN JoinProducts(left,right);
- OR_IF right IS Constant THEN
- RETURN AddToProduct(left,right)
- ELSE
- Product(left).InsertLast(right);
- RETURN left;
- END
- OR_IF right IS Product THEN
- IF left IS Constant THEN
- RETURN AddToProduct(right,left)
- ELSE
- Product(right).InsertFirst(left);
- RETURN right;
- END;
- ELSE
- prod:=Product.Create(func);
- prod.InsertLast(left);
- prod.InsertLast(right);
- RETURN prod;
- END;
- END BuildProduct;
-
-
- TYPE
- F_SIN = POINTER TO OBJECT OF SimpleFunction;
- METHOD Eval():LONGREAL;
- METHOD Diff(func : Function;after : Variable):Expression;
- METHOD AppendOn(VAR str : STRING);
- METHOD StringLen():INTEGER;
- END;
-
- F_COS = POINTER TO OBJECT OF SimpleFunction;
- METHOD Eval():LONGREAL;
- METHOD Diff(func : Function;after : Variable):Expression;
- METHOD AppendOn(VAR str : STRING);
- METHOD StringLen():INTEGER;
- END;
-
- F_EXP = POINTER TO OBJECT OF SimpleFunction;
- METHOD Eval():LONGREAL;
- METHOD AppendOn(VAR str : STRING);
- METHOD StringLen():INTEGER;
- END;
-
- F_SQRT = POINTER TO OBJECT OF SimpleFunction;
- METHOD Eval():LONGREAL;
- METHOD AppendOn(VAR str : STRING);
- METHOD StringLen():INTEGER;
- END;
-
- F_LOG = POINTER TO OBJECT OF SimpleFunction;
- METHOD Eval():LONGREAL;
- METHOD AppendOn(VAR str : STRING);
- METHOD StringLen():INTEGER;
- END;
-
- F_LN = POINTER TO OBJECT OF SimpleFunction;
- METHOD Eval():LONGREAL;
- METHOD AppendOn(VAR str : STRING);
- METHOD StringLen():INTEGER;
- END;
-
- F_TAN = POINTER TO OBJECT OF SimpleFunction;
- METHOD Eval():LONGREAL;
- METHOD AppendOn(VAR str : STRING);
- METHOD StringLen():INTEGER;
- END;
-
- F_ASIN = POINTER TO OBJECT OF SimpleFunction;
- METHOD Eval():LONGREAL;
- METHOD AppendOn(VAR str : STRING);
- METHOD StringLen():INTEGER;
- END;
-
- F_ACOS = POINTER TO OBJECT OF SimpleFunction;
- METHOD Eval():LONGREAL;
- METHOD AppendOn(VAR str : STRING);
- METHOD StringLen():INTEGER;
- END;
-
- F_ABS = POINTER TO OBJECT OF SimpleFunction;
- METHOD Eval():LONGREAL;
- METHOD AppendOn(VAR str : STRING);
- METHOD StringLen():INTEGER;
- END;
-
- F_SGN = POINTER TO OBJECT OF SimpleFunction;
- METHOD Eval():LONGREAL;
- METHOD AppendOn(VAR str : STRING);
- METHOD StringLen():INTEGER;
- END;
-
- F_ATAN = POINTER TO OBJECT OF SimpleFunction;
- METHOD Eval():LONGREAL;
- METHOD AppendOn(VAR str : STRING);
- METHOD StringLen():INTEGER;
- END;
-
- METHOD F_SIN.Eval():LONGREAL;
- BEGIN
- RETURN SIN(of.Eval());
- END Eval;
-
- METHOD F_SIN.Diff(func : Function;after : Variable):Expression;
- BEGIN
- RETURN BuildProduct(func,of.Diff(func,after),
- F_COS.Create(func,of.FClone(func)));
- END Diff;
-
- METHOD F_SIN.AppendOn(VAR str : STRING);
- BEGIN
- Strings.Append(str,"SIN(");
- of.AppendOn(str);
- Strings.Append(str,")");
- END AppendOn;
-
- METHOD F_SIN.StringLen():INTEGER;
- BEGIN
- RETURN "SIN".len+2+of.StringLen();
- END StringLen;
-
-
- METHOD F_COS.Eval():LONGREAL;
- BEGIN
- RETURN COS(of.Eval());
- END Eval;
-
- METHOD F_COS.Diff(func : Function;after : Variable):Expression;
- BEGIN
- RETURN BuildProduct(func,of.Diff(func,after),
- Negation.Create(func,
- F_SIN.Create(func,of.FClone(func))));
- END Diff;
-
- METHOD F_COS.AppendOn(VAR str : STRING);
- BEGIN
- Strings.Append(str,"COS(");
- of.AppendOn(str);
- Strings.Append(str,")");
- END AppendOn;
-
- METHOD F_COS.StringLen():INTEGER;
- BEGIN
- RETURN "COS".len+2+of.StringLen();
- END StringLen;
-
-
- METHOD F_EXP.Eval():LONGREAL;
- BEGIN
- RETURN EXP(of.Eval());
- END Eval;
-
- METHOD F_EXP.AppendOn(VAR str : STRING);
- BEGIN
- Strings.Append(str,"EXP(");
- of.AppendOn(str);
- Strings.Append(str,")");
- END AppendOn;
-
- METHOD F_EXP.StringLen():INTEGER;
- BEGIN
- RETURN "EXP".len+2+of.StringLen();
- END StringLen;
-
-
- METHOD F_SQRT.Eval():LONGREAL;
- BEGIN
- RETURN SQRT(of.Eval());
- END Eval;
-
- METHOD F_SQRT.AppendOn(VAR str : STRING);
- BEGIN
- Strings.Append(str,"SQRT(");
- of.AppendOn(str);
- Strings.Append(str,")");
- END AppendOn;
-
- METHOD F_SQRT.StringLen():INTEGER;
- BEGIN
- RETURN "SQRT".len+2+of.StringLen();
- END StringLen;
-
-
- METHOD F_LOG.Eval():LONGREAL;
- BEGIN
- RETURN LOG(of.Eval());
- END Eval;
-
- METHOD F_LOG.AppendOn(VAR str : STRING);
- BEGIN
- Strings.Append(str,"LOG(");
- of.AppendOn(str);
- Strings.Append(str,")");
- END AppendOn;
-
- METHOD F_LOG.StringLen():INTEGER;
- BEGIN
- RETURN "LOG".len+2+of.StringLen();
- END StringLen;
-
-
- METHOD F_LN.Eval():LONGREAL;
- BEGIN
- RETURN LN(of.Eval());
- END Eval;
-
- METHOD F_LN.AppendOn(VAR str : STRING);
- BEGIN
- Strings.Append(str,"LN(");
- of.AppendOn(str);
- Strings.Append(str,")");
- END AppendOn;
-
- METHOD F_LN.StringLen():INTEGER;
- BEGIN
- RETURN "LN".len+2+of.StringLen();
- END StringLen;
-
-
- METHOD F_TAN.Eval():LONGREAL;
- BEGIN
- RETURN TAN(of.Eval());
- END Eval;
-
- METHOD F_TAN.AppendOn(VAR str : STRING);
- BEGIN
- Strings.Append(str,"TAN(");
- of.AppendOn(str);
- Strings.Append(str,")");
- END AppendOn;
-
- METHOD F_TAN.StringLen():INTEGER;
- BEGIN
- RETURN "TAN".len+2+of.StringLen();
- END StringLen;
-
-
- METHOD F_ASIN.Eval():LONGREAL;
- BEGIN
- RETURN ASIN(of.Eval());
- END Eval;
-
- METHOD F_ASIN.AppendOn(VAR str : STRING);
- BEGIN
- Strings.Append(str,"ASIN(");
- of.AppendOn(str);
- Strings.Append(str,")");
- END AppendOn;
-
- METHOD F_ASIN.StringLen():INTEGER;
- BEGIN
- RETURN "ASIN".len+2+of.StringLen();
- END StringLen;
-
-
- METHOD F_ACOS.Eval():LONGREAL;
- BEGIN
- RETURN ACOS(of.Eval());
- END Eval;
-
- METHOD F_ACOS.AppendOn(VAR str : STRING);
- BEGIN
- Strings.Append(str,"ACOS(");
- of.AppendOn(str);
- Strings.Append(str,")");
- END AppendOn;
-
- METHOD F_ACOS.StringLen():INTEGER;
- BEGIN
- RETURN "ACOS".len+2+of.StringLen();
- END StringLen;
-
-
- METHOD F_ABS.Eval():LONGREAL;
- BEGIN
- RETURN ABS(of.Eval());
- END Eval;
-
- METHOD F_ABS.AppendOn(VAR str : STRING);
- BEGIN
- Strings.Append(str,"ABS(");
- of.AppendOn(str);
- Strings.Append(str,")");
- END AppendOn;
-
- METHOD F_ABS.StringLen():INTEGER;
- BEGIN
- RETURN "ABS".len+2+of.StringLen();
- END StringLen;
-
-
- METHOD F_SGN.Eval():LONGREAL;
- VAR val : LONGREAL;
- BEGIN
- val:=of.Eval();
- IF val<0 THEN
- RETURN -1.0
- OR_IF val>0 THEN
- RETURN 1.0
- ELSE
- RETURN 0.0
- END;
- END Eval;
-
- METHOD F_SGN.AppendOn(VAR str : STRING);
- BEGIN
- Strings.Append(str,"SGN(");
- of.AppendOn(str);
- Strings.Append(str,")");
- END AppendOn;
-
- METHOD F_SGN.StringLen():INTEGER;
- BEGIN
- RETURN "SGN".len+2+of.StringLen();
- END StringLen;
-
-
- METHOD F_ATAN.Eval():LONGREAL;
- BEGIN
- RETURN ATAN(of.Eval());
- END Eval;
-
- METHOD F_ATAN.AppendOn(VAR str : STRING);
- BEGIN
- Strings.Append(str,"ATAN(");
- of.AppendOn(str);
- Strings.Append(str,")");
- END AppendOn;
-
- METHOD F_ATAN.StringLen():INTEGER;
- BEGIN
- RETURN "ATAN".len+2+of.StringLen();
- END StringLen;
-
-
-
- METHOD Expression.toString():STRING;
- VAR i : INTEGER;
- BEGIN
- i:=SELF.StringLen();
- ALLOC_RESULT(i+1);
- ASSERT(i<RESULT'RANGE,RangeViolation);
- RESULT:="";
- SELF.AppendOn(RESULT);
- END toString;
-
- METHOD Expression.Delete;BEGIN END Delete;
-
- METHOD SimpleFunction.Delete;
- BEGIN
- of.Delete;
- END Delete;
-
- METHOD ExpressionList.Delete;
- BEGIN
- SELF.DeleteAll;
- END Delete;
-
- METHOD Potenz.Delete;
- BEGIN
- base.Delete;
- exponent.Delete;
- END Delete;
-
- METHOD Potenz.FClone(func : Function):Expression;
- BEGIN
- RETURN Potenz.Create(func,base.FClone(func),exponent.FClone(func));
- END FClone;
-
- METHOD ExpressionList.FClone(func : Function):Expression;
- VAR sum : ExpressionList;
- ex : Expression;
- BEGIN
- sum:=CLONE(SELF);sum.first:=NIL;sum.last:=NIL;
- Resources.ChangeObjContext(sum,func.con);
-
- ex:=first;
- WHILE ex#NIL DO
- sum.InsertLast(ex.FClone(func));
- ex:=ex.next;
- END;
- RETURN sum;
- END FClone;
-
- METHOD SimpleFunction.FClone(func : Function):Expression;
- VAR f : SimpleFunction;
- BEGIN
- f:=CLONE(SELF);
- Resources.ChangeObjContext(f,func.con);
- f.of:=of.FClone(func);
- RETURN f;
- END FClone;
-
- METHOD Expression.Create(func : Function):Expression;
- BEGIN
- Resources.ChangeObjContext(SELF,func.con);
- RETURN SELF;
- END Create;
-
- METHOD Indirection.Eval():LONGREAL;
- BEGIN
- RETURN of.Eval();
- END Eval;
-
- METHOD Indirection.StringLen():INTEGER;
- BEGIN
- RETURN of.StringLen();
- END StringLen;
-
- METHOD Indirection.AppendOn(VAR str : STRING);
- BEGIN
- of.AppendOn(str);
- END AppendOn;
-
- METHOD Indirection.Diff(func : Function;
- after : Variable):Expression;
- BEGIN
- RETURN of.Diff(func,after);
- END Diff;
-
- METHOD Indirection.Delete;BEGIN END Delete;
-
-
- METHOD Constant.Eval():LONGREAL;
- BEGIN
- RETURN value
- END Eval;
-
- METHOD Constant.Create(func : Function;
- value : LONGREAL):Expression;
- BEGIN
- SELF.value:=value;
- RETURN SUPER.Create(func);
- END Create;
-
- METHOD Constant.FClone(func : Function):Expression;
- BEGIN
- RETURN Constant.Create(func,value);
- END FClone;
-
- METHOD Constant.StringLen():INTEGER;
- BEGIN
- RETURN 10;
- END StringLen;
-
- METHOD Constant.AppendOn(VAR str : STRING);
- BEGIN
- Strings.Append(str,RealToString(value,10,5));
- END AppendOn;
-
- METHOD Constant.Diff(func : Function;after : Variable):Expression;
- BEGIN
- RETURN Constant.Create(func,0.0);
- END Diff;
-
- METHOD Variable.Eval():LONGREAL;
- BEGIN
- RETURN value
- END Eval;
-
- METHOD Variable.Diff(func : Function;after : Variable):Expression;
- BEGIN
- IF SELF=after THEN
- RETURN Constant.Create(func,1.0);
- ELSE
- RETURN Constant.Create(func,0.0);
- END;
- END Diff;
-
- METHOD Variable.StringLen():INTEGER;
- BEGIN
- RETURN name.len;
- END StringLen;
-
- METHOD Variable.AppendOn(VAR str : STRING);
- BEGIN
- Strings.Append(str,name);
- END AppendOn;
-
-
- METHOD Summation.Eval():LONGREAL;
- VAR val : LONGREAL;
- e : Expression;
- BEGIN
- val:=0.0;
- e:=first;
- WHILE e#NIL DO val:=val+e.Eval();e:=e.next END;
- RETURN val;
- END Eval;
-
- METHOD Summation.Diff(func : Function;after : Variable):Expression;
- VAR ex,dif : Expression;
- const : Constant := NIL;
- sum : Summation := NIL;
- var : Expression := NIL;
- BEGIN
- ex:=first;
- WHILE ex#NIL DO
- dif:=ex.Diff(func,after);
- IF dif IS Constant THEN
- IF const#NIL THEN
- const.value:=const.value+Constant(dif).value;
- DISPOSE(dif);
- ELSE
- const:=dif
- END;
- OR_IF sum#NIL THEN
- sum.InsertLast(dif);
- OR_IF var#NIL THEN
- sum:=Summation.Create(func);
- sum.InsertLast(var);
- sum.InsertLast(dif);
- ELSE
- var:=dif
- END;
- ex:=ex.next;
- END;
- IF (const#NIL) AND (const.value=0.0) AND ((sum#NIL) OR (var#NIL)) THEN
- DISPOSE(const);const:=NIL;
- END;
- IF const=NIL THEN
- IF sum#NIL THEN
- RETURN sum
- ELSE
- RETURN var
- END
- ELSE
- IF sum#NIL THEN
- sum.InsertLast(const);
- RETURN sum;
- OR_IF var#NIL THEN
- sum:=Summation.Create(func);
- sum.InsertLast(var);
- sum.InsertLast(const);
- RETURN sum;
- ELSE
- RETURN const;
- END;
- END;
- END Diff;
-
- METHOD Product.Diff(func : Function;after : Variable):Expression;
- VAR left,
- right : Expression;
- ret : Expression;
- BEGIN
- left:=first;
- IF first.next=last THEN
- right:=last;
- ELSE
- SELF.RemoveNode(left);
- right:=SELF;
- END;
- ret:=BuildSum(func,
- BuildProduct(func,left.FClone(func),right.Diff(func,after)),
- BuildProduct(func,left.Diff(func,after),right.FClone(func)));
- IF left#first THEN
- SELF.InsertFirst(left)
- END;
- RETURN ret;
- END Diff;
-
- METHOD Summation.StringLen():INTEGER;
- VAR len : INTEGER;
- ex : Expression;
- BEGIN
- len:=first.StringLen();
- ex:=first.next;
- WHILE ex#NIL DO
- IF ex IS Negation THEN
- INC(len,Negation(ex).of.StringLen()+1);
- ELSE
- INC(len,ex.StringLen()+1);
- END;
- ex:=ex.next;
- END;
- RETURN len;
- END StringLen;
-
- METHOD Summation.AppendOn(VAR str : STRING);
- VAR ex : Expression;
- BEGIN
- first.AppendOn(str);
- ex:=first.next;
- WHILE ex#NIL DO
- IF ex IS Negation THEN
- Strings.Append(str,"-");
- Negation(ex).of.AppendOn(str);
- ELSE
- Strings.Append(str,"+");
- ex.AppendOn(str);
- END;
- ex:=ex.next;
- END;
- END AppendOn;
-
- METHOD Product.Eval():LONGREAL;
- VAR val : LONGREAL;
- e : Expression;
- BEGIN
- val:=1.0;
- e:=first;
- WHILE e#NIL DO val:=val*e.Eval();e:=e.next END;
- RETURN val;
- END Eval;
-
-
- METHOD Product.StringLen():INTEGER;
- VAR len : INTEGER;
- ex : Expression;
- BEGIN
- IF first IS Summation THEN
- len:=first.StringLen()+2;
- ELSE
- len:=first.StringLen();
- END;
- ex:=first.next;
- WHILE ex#NIL DO
- IF ex IS Reciproke THEN
- IF Reciproke(ex).of IS Summation THEN
- INC(len,Reciproke(ex).of.StringLen()+3);
- ELSE
- INC(len,Reciproke(ex).of.StringLen()+1);
- END;
- ELSE
- IF ex IS Summation THEN
- INC(len,ex.StringLen()+3);
- ELSE
- INC(len,ex.StringLen()+1);
- END;
- END;
- ex:=ex.next;
- END;
- RETURN len;
- END StringLen;
-
- METHOD Product.AppendOn(VAR str : STRING);
- VAR ex : Expression;
- BEGIN
- IF first IS Summation THEN
- Strings.Append(str,"(");
- first.AppendOn(str);
- Strings.Append(str,")");
- ELSE
- first.AppendOn(str);
- END;
- ex:=first.next;
- WHILE ex#NIL DO
- IF ex IS Reciproke THEN
- Strings.Append(str,"/");
- IF Reciproke(ex).of IS Summation THEN
- Strings.Append(str,"(");
- Reciproke(ex).of.AppendOn(str);
- Strings.Append(str,")");
- ELSE
- Reciproke(ex).of.AppendOn(str);
- END;
- ELSE
- Strings.Append(str,"*");
- IF ex IS Summation THEN
- Strings.Append(str,"(");
- ex.AppendOn(str);
- Strings.Append(str,")");
- ELSE
- ex.AppendOn(str);
- END
- END;
- ex:=ex.next;
- END;
- END AppendOn;
-
- METHOD SimpleFunction.Create(func : Function;
- of : Expression):Expression;
- BEGIN
- SELF.of:=of;
- FORGET SUPER.Create(func);
- IF of IS Constant THEN
- Constant(of).value:=SELF.Eval();
- DISPOSE(SELF);
- RETURN of
- ELSE
- RETURN SELF
- END;
- END Create;
-
- METHOD Negation.Eval():LONGREAL;
- BEGIN
- RETURN -of.Eval();
- END Eval;
-
- METHOD Negation.Diff(func : Function;after : Variable):Expression;
- VAR dif : Expression;
- BEGIN
- dif:=of.Diff(func,after);
- IF dif IS Constant THEN
- Constant(dif).value:=-Constant(dif).value;
- RETURN dif
- ELSE
- RETURN Negation.Create(func,dif)
- END;
- END Diff;
-
- METHOD Negation.StringLen():INTEGER;
- BEGIN
- IF of IS Summation THEN
- RETURN of.StringLen()+3
- ELSE
- RETURN of.StringLen()+1
- END;
- END StringLen;
-
- METHOD Negation.AppendOn(VAR str : STRING);
- BEGIN
- IF of IS Summation THEN
- Strings.Append(str,"-(");
- of.AppendOn(str);
- Strings.Append(str,")");
- ELSE
- Strings.Append(str,"-");
- of.AppendOn(str);
- END;
- END AppendOn;
-
- METHOD Reciproke.Eval():LONGREAL;
- VAR val : LONGREAL;
- BEGIN
- val:=of.Eval();
- ASSERT(val#0.0,DivisionByZero);
- RETURN 1.0/of.Eval();
- END Eval;
-
- METHOD Reciproke.Diff(func : Function;after : Variable):Expression;
- BEGIN
- RETURN Negation.Create(func,
- BuildProduct(func,of.Diff(func,after),
- Reciproke.Create(func,
- Potenz.Create(func,of.FClone(func),Constant.Create(func,2.0)))));
- END Diff;
-
- METHOD Reciproke.StringLen():INTEGER;
- BEGIN
- IF (of IS Summation) OR (of IS Product) THEN
- RETURN of.StringLen()+4
- ELSE
- RETURN of.StringLen()+2
- END;
- END StringLen;
-
- METHOD Reciproke.AppendOn(VAR str : STRING);
- BEGIN
- IF (of IS Summation) OR (of IS Product) THEN
- Strings.Append(str,"1/(");
- of.AppendOn(str);
- Strings.Append(str,")");
- ELSE
- Strings.Append(str,"1/");
- of.AppendOn(str);
- END;
- END AppendOn;
-
- METHOD Potenz.Create(func : Function;
- base,ex : Expression):Expression;
- BEGIN
- IF (ex IS Constant) AND (Constant(ex).value=0.0) THEN
- base.Delete;
- ex.Delete;
- DISPOSE(SELF);
- RETURN Constant.Create(func,1.0);
- OR_IF (base IS Constant) AND ((Constant(base).value=1.0) OR
- (Constant(base).value=0.0)) THEN
- ex.Delete;
- DISPOSE(SELF);
- RETURN base;
- OR_IF (ex IS Constant) AND (Constant(ex).value=1.0) THEN
- ex.Delete;
- DISPOSE(SELF);
- RETURN base;
- OR_IF (base IS Constant) AND (ex IS Constant) THEN
- Constant(base).value:=Constant(base).value^Constant(ex).value;
- ex.Delete;
- DISPOSE(SELF);
- RETURN base;
- ELSE
- SELF.base:=base;
- SELF.exponent:=ex;
- RETURN SUPER.Create(func);
- END;
- END Create;
-
- METHOD Potenz.Eval():LONGREAL;
- BEGIN
- RETURN base.Eval()^exponent.Eval();
- END Eval;
-
- METHOD Potenz.Diff(func : Function;after : Variable):Expression;
- BEGIN
- RETURN BuildSum(func,
- BuildProduct(func,
- BuildProduct(func,Potenz.Create(func,base.FClone(func),
- exponent.FClone(func)),
- exponent.Diff(func,after)),
- F_LN.Create(func,base.FClone(func))),
- BuildProduct(func,
- BuildProduct(func,base.Diff(func,after),
- exponent.FClone(func)),
- Potenz.Create(func,base.FClone(func),
- BuildSum(func,exponent.FClone(func),
- Constant.Create(func,-1)))));
- END Diff;
-
- METHOD Potenz.StringLen():INTEGER;
- VAR len : INTEGER;
- BEGIN
- len:=base.StringLen()+exponent.StringLen()+1;
- IF (base IS Summation) OR (base IS Product) OR (base IS Potenz) THEN
- INC(len,2);
- END;
- IF (exponent IS Summation) OR (exponent IS Product) OR (exponent IS Potenz) THEN
- INC(len,2);
- END;
- RETURN len;
- END StringLen;
-
- METHOD Potenz.AppendOn(VAR str : STRING);
- BEGIN
- IF (base IS Summation) OR (base IS Product) OR (base IS Potenz) THEN
- Strings.Append(str,"(");
- base.AppendOn(str);
- Strings.Append(str,")");
- ELSE
- base.AppendOn(str);
- END;
- Strings.Append(str,"^");
- IF (exponent IS Summation) OR (exponent IS Product) OR (exponent IS Potenz) THEN
- Strings.Append(str,"(");
- exponent.AppendOn(str);
- Strings.Append(str,")");
- ELSE
- exponent.AppendOn(str);
- END;
- END AppendOn;
-
- METHOD Variable.Create( func : Function;
- REF name : STRING);
- BEGIN
- Resources.ChangeObjContext(SELF,func.con);
- SELF.name:=name;
- func.varDict.Add(name,SELF);
- END Create;
-
- METHOD Variable.FClone(func : Function):Expression;
- BEGIN
- RETURN func.varDict.Search(name);
- END FClone;
-
- METHOD Function.Create(REF str : STRING;
- context : ContextPtr;
- REF vars : LIST OF STRING);
-
- VAR self : Function;
-
- VAR
- cpos : INTEGER;
- act : CHAR;
-
- PROCEDURE Next;
- BEGIN
- ASSERT(cpos<=str.len,SyntaxError);
- INC(cpos);
- act:=str.data[cpos];
- END Next;
-
- PROCEDURE Init;
- BEGIN
- cpos:=0;
- act:=str.data[0]
- END Init;
-
- PROCEDURE ParseSumme():Expression;
-
- PROCEDURE ParseProduct():Expression;
-
- PROCEDURE ParsePotenz():Expression;
-
- PROCEDURE ParseItem():Expression;
- VAR ex,hlp : Expression;
- str : STRING(40);
- BEGIN
- IF KEY act
- OF "0".."9" THEN
- str.len:=0;
- WHILE act OF "0".."9" DO
- str.data[str.len]:=act;INC(str.len);Next
- END;
- IF act="." THEN
- str.data[str.len]:=act;INC(str.len);Next;
- WHILE act OF "0".."9" DO
- str.data[str.len]:=act;INC(str.len);Next
- END;
- END;
- IF act OF "e","E" THEN
- str.data[str.len]:=act;INC(str.len);Next;
- IF act="-" THEN
- str.data[str.len]:=act;INC(str.len);Next;
- END;
- WHILE act OF "0".."9" DO
- str.data[str.len]:=act;INC(str.len);Next
- END;
- END;
- str.data[str.len]:=&0;
- ex:=Constant.Create(self,StringToReal(str));
- END
- OF "(" THEN
- Next;
- ex:=ParseSumme();
- ASSERT(act=")",SyntaxError);
- Next;
- END
- OF "-" THEN
- Next;
- hlp:=ParseItem();
- IF hlp IS Constant THEN
- ex:=hlp;
- Constant(ex).value:=-Constant(ex).value
- ELSE
- ex:=Negation.Create(self,hlp);
- END;
- END
- OF "a".."z",
- "A".."Z" THEN
- str.len:=0;
- WHILE act OF "a".."z","A".."Z","0".."9" DO
- str.data[str.len]:=act;INC(str.len);Next
- END;
- str.data[str.len]:=&0;
- IF CapsEqual(str,"SIN") THEN
- ASSERT(act="(",SyntaxError);Next;
- ex:=F_SIN.Create(self,ParseSumme());
- ASSERT(act=")",SyntaxError);Next
- OR_IF CapsEqual(str,"COS") THEN
- ASSERT(act="(",SyntaxError);Next;
- ex:=F_COS.Create(self,ParseSumme());
- ASSERT(act=")",SyntaxError);Next
- OR_IF CapsEqual(str,"EXP") THEN
- ASSERT(act="(",SyntaxError);Next;
- ex:=F_EXP.Create(self,ParseSumme());
- ASSERT(act=")",SyntaxError);Next
- OR_IF CapsEqual(str,"SQRT") THEN
- ASSERT(act="(",SyntaxError);Next;
- ex:=F_SQRT.Create(self,ParseSumme());
- ASSERT(act=")",SyntaxError);Next
- OR_IF CapsEqual(str,"LOG") THEN
- ASSERT(act="(",SyntaxError);Next;
- ex:=F_LOG.Create(self,ParseSumme());
- ASSERT(act=")",SyntaxError);Next
- OR_IF CapsEqual(str,"LN") THEN
- ASSERT(act="(",SyntaxError);Next;
- ex:=F_LN.Create(self,ParseSumme());
- ASSERT(act=")",SyntaxError);Next
- OR_IF CapsEqual(str,"TAN") THEN
- ASSERT(act="(",SyntaxError);Next;
- ex:=F_TAN.Create(self,ParseSumme());
- ASSERT(act=")",SyntaxError);Next
- OR_IF CapsEqual(str,"ASIN") THEN
- ASSERT(act="(",SyntaxError);Next;
- ex:=F_ASIN.Create(self,ParseSumme());
- ASSERT(act=")",SyntaxError);Next
- OR_IF CapsEqual(str,"ACOS") THEN
- ASSERT(act="(",SyntaxError);Next;
- ex:=F_ACOS.Create(self,ParseSumme());
- ASSERT(act=")",SyntaxError);Next
- OR_IF CapsEqual(str,"ABS") THEN
- ASSERT(act="(",SyntaxError);Next;
- ex:=F_ABS.Create(self,ParseSumme());
- ASSERT(act=")",SyntaxError);Next
- OR_IF CapsEqual(str,"SGN") THEN
- ASSERT(act="(",SyntaxError);Next;
- ex:=F_SGN.Create(self,ParseSumme());
- ASSERT(act=")",SyntaxError);Next
- OR_IF CapsEqual(str,"ATAN") THEN
- ASSERT(act="(",SyntaxError);Next;
- ex:=F_ATAN.Create(self,ParseSumme());
- ASSERT(act=")",SyntaxError);Next
- ELSE
- ex:=Indirection.Create(self,varDict.Search(str));
- END;
- END
- ELSE
- RAISE(SyntaxError);
- END;
- RETURN ex;
- END ParseItem;
-
- VAR help,pot : Expression;
-
- BEGIN
- pot:=ParseItem();
- WHILE act="^" DO
- Next;
- pot:=Potenz.Create(self,pot,ParseItem());
- END;
- RETURN pot;
- END ParsePotenz;
-
- VAR const : Constant;
- prod : Product;
- var : Expression;
- help : Expression;
-
- BEGIN
- prod:=NIL;
- const:=NIL;
- var:=ParsePotenz();
- IF var IS Constant THEN const:=var;var:=NIL END;
- WHILE KEY act
- OF "*" DO
- Next;
- help:=ParsePotenz();
- IF help IS Constant THEN
- IF const#NIL THEN
- const.value:=const.value*Constant(help).value;
- DISPOSE(help);
- ELSE
- const:=help
- END;
- OR_IF prod#NIL THEN
- prod.InsertLast(help);
- OR_IF var#NIL THEN
- prod:=Product.Create(self);
- prod.InsertLast(var);
- prod.InsertLast(help);
- ELSE
- var:=help;
- END;
- END
- OF "/" DO
- Next;
- help:=ParsePotenz();
- IF help IS Constant THEN
- ASSERT(Constant(help).value#0.0,DivisionByZero);
- IF const#NIL THEN
- const.value:=const.value/Constant(help).value;
- DISPOSE(help);
- ELSE
- const:=help;
- const.value:=1.0/const.value;
- END;
- OR_IF prod#NIL THEN
- prod.InsertLast(Reciproke.Create(self,help));
- OR_IF var#NIL THEN
- prod:=Product.Create(self);
- prod.InsertLast(var);
- prod.InsertLast(Reciproke.Create(self,help));
- ELSE
- var:=Reciproke.Create(self,help);
- END;
- END
- END;
- IF (const#NIL) AND (const.value=1.0) AND ((prod#NIL) OR (var#NIL)) THEN
- DISPOSE(const);const:=NIL;
- END;
- IF const=NIL THEN
- IF prod#NIL THEN
- RETURN prod
- ELSE
- RETURN var
- END
- ELSE
- IF prod#NIL THEN
- prod.InsertLast(const);
- RETURN prod;
- OR_IF var#NIL THEN
- prod:=Product.Create(self);
- prod.InsertLast(var);
- prod.InsertLast(const);
- RETURN prod;
- ELSE
- RETURN const;
- END;
- END;
- END ParseProduct;
-
-
- VAR const : Constant;
- sum : Summation;
- var : Expression;
- help : Expression;
-
- BEGIN
- sum:=NIL;
- const:=NIL;
- var:=ParseProduct();
- IF var IS Constant THEN const:=var;var:=NIL END;
- WHILE KEY act
- OF "+" DO
- Next;
- help:=ParseProduct();
- IF help IS Constant THEN
- IF const#NIL THEN
- const.value:=const.value+Constant(help).value;
- DISPOSE(help);
- ELSE
- const:=help
- END;
- OR_IF sum#NIL THEN
- sum.InsertLast(help);
- OR_IF var#NIL THEN
- sum:=Summation.Create(self);
- sum.InsertLast(var);
- sum.InsertLast(help);
- ELSE
- var:=help;
- END;
- END
- OF "-" DO
- Next;
- help:=ParseProduct();
- IF help IS Constant THEN
- IF const#NIL THEN
- const.value:=const.value-Constant(help).value;
- DISPOSE(help);
- ELSE
- const:=help;
- const.value:=-const.value;
- END;
- OR_IF sum#NIL THEN
- sum.InsertLast(Negation.Create(self,help));
- OR_IF var#NIL THEN
- sum:=Summation.Create(self);
- sum.InsertLast(var);
- sum.InsertLast(Negation.Create(self,help));
- ELSE
- var:=Negation.Create(self,help);
- END;
- END
- END;
- IF (const#NIL) AND (const.value=0.0) AND ((sum#NIL) OR (var#NIL)) THEN
- DISPOSE(const);const:=NIL;
- END;
- IF const=NIL THEN
- IF sum#NIL THEN
- RETURN sum
- ELSE
- RETURN var
- END
- ELSE
- IF sum#NIL THEN
- sum.InsertLast(const);
- RETURN sum;
- OR_IF var#NIL THEN
- sum:=Summation.Create(self);
- sum.InsertLast(var);
- sum.InsertLast(const);
- RETURN sum;
- ELSE
- RETURN const;
- END;
- END;
- END ParseSumme;
-
- VAR i : INTEGER;
- BEGIN
- self:=SELF;
- IF context#NIL THEN
- Resources.ChangeObjContext(SELF,context);
- END;
- TRY
- con:=Resources.Create_Context(context);
- varDict.Create(con);
- variables'RANGE:=vars'RANGE;
- New(variables);
- FOR i:=0 TO vars'MAX DO
- variables[i].Create(SELF,vars[i]);
- END;
- Init;
- ex:=ParseSumme();
- ASSERT(act=&0,SyntaxError);
- EXCEPT ELSE
- SELF.Delete;
- END;
- END Create;
-
- METHOD Function.Differentiate( of : Function;
- REF after : STRING;
- context : ContextPtr);
- VAR i : INTEGER;
- BEGIN
- IF context#NIL THEN
- Resources.ChangeObjContext(SELF,context);
- END;
- TRY
- con:=Resources.Create_Context(context);
- varDict.Create(con);
- variables'RANGE:=of.variables'RANGE;
- New(variables);
- FOR i:=0 TO variables'MAX DO
- variables[i].Create(SELF,of.variables[i].name);
- END;
- ex:=of.ex.Diff(SELF,of.varDict.Search(after));
- EXCEPT ELSE
- SELF.Delete;
- END;
- END Differentiate;
-
-
- METHOD Function.Eval(vars : LIST OF LONGREAL):LONGREAL;
- VAR i : INTEGER;
- BEGIN
- ASSERT(vars'RANGE=variables'RANGE,WrongParamsNum);
- FOR i:=0 TO vars'MAX DO
- variables[i].value:=vars[i]
- END;
- RETURN ex.Eval();
- END Eval;
-
- METHOD Function.toString():STRING;
- VAR len : INTEGER;
- BEGIN
- len:=ex.StringLen();
- ALLOC_RESULT(len+1);
- ASSERT(len<RESULT'RANGE,RangeViolation);
- RESULT:="";
- ex.AppendOn(RESULT);
- END toString;
-
- METHOD Function.Delete;
- BEGIN
- Resources.Delete_Context(con);
- END Delete;
-
- PROCEDURE CheckFunction(REF str : STRING;
- REF vars : LIST OF STRING):INTEGER;
- VAR
- cpos : INTEGER;
- act : CHAR;
-
- PROCEDURE Next;
- BEGIN
- ASSERT(cpos<=str.len,SyntaxError);
- INC(cpos);
- act:=str.data[cpos];
- END Next;
-
- PROCEDURE Init;
- BEGIN
- cpos:=0;
- act:=str.data[0]
- END Init;
-
- PROCEDURE ParseSumme;
-
- PROCEDURE ParseProduct;
-
- PROCEDURE ParsePotenz;
-
- PROCEDURE ParseItem;
- VAR str : STRING(20);
- i : INTEGER;
- BEGIN
- IF KEY act
- OF "0".."9" THEN
- WHILE act OF "0".."9" DO
- Next
- END;
- IF act="." THEN
- Next;
- WHILE act OF "0".."9" DO
- Next
- END;
- END;
- IF act OF "e","E" THEN
- Next;
- IF act="-" THEN
- Next;
- END;
- WHILE act OF "0".."9" DO
- Next
- END;
- END;
- END
- OF "(" THEN
- Next;
- ParseSumme;
- ASSERT(act=")",SyntaxError);
- Next;
- END
- OF "-" THEN
- Next;
- ParseItem;
- END
- OF "a".."z",
- "A".."Z" THEN
- str.len:=0;
- WHILE act OF "a".."z","A".."Z","0".."9" DO
- str.data[str.len]:=act;INC(str.len);Next
- END;
- str.data[str.len]:=&0;
- IF CapsEqual(str,"SIN") OR
- CapsEqual(str,"COS") OR
- CapsEqual(str,"EXP") OR
- CapsEqual(str,"SQRT") OR
- CapsEqual(str,"LOG") OR
- CapsEqual(str,"LN") OR
- CapsEqual(str,"TAN") OR
- CapsEqual(str,"ASIN") OR
- CapsEqual(str,"ACOS") OR
- CapsEqual(str,"ABS") OR
- CapsEqual(str,"SGN") OR
- CapsEqual(str,"ATAN") THEN
- ASSERT(act="(",SyntaxError);Next;
- ParseSumme;
- ASSERT(act=")",SyntaxError);Next
- ELSE
- i:=0;
- WHILE (i<vars'RANGE) AND NOT Str.Equal(str,vars[i]) DO
- INC(i);
- END;
- ASSERT(i<vars'RANGE,SyntaxError);
- END;
- END
- ELSE
- RAISE(SyntaxError);
- END;
- END ParseItem;
-
- BEGIN
- ParseItem;
- WHILE act="^" DO
- Next;
- ParseItem;
- END;
- END ParsePotenz;
-
- BEGIN
- ParsePotenz;
- WHILE act OF "*","/" DO
- Next;
- ParsePotenz;
- END;
- END ParseProduct;
-
- BEGIN
- ParseProduct;
- WHILE act OF "+","-" DO
- Next;
- ParseProduct;
- END;
- END ParseSumme;
-
- BEGIN
- TRY
- Init;
- ParseSumme;
- ASSERT(act=&0,SyntaxError);
- cpos:=-1;
- EXCEPT
- OF SyntaxError THEN END;
- END;
- RETURN cpos
- END CheckFunction;
-
-
- END OFunctions.
-